package com.ruoyi.web.utils.qg_pay.entity;

import com.ruoyi.web.utils.ReflectUtil;
import com.ruoyi.web.utils.qg_pay.exception.QueryParamException;
import lombok.Data;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * url参数map
 *
 * @since 2023/1/17 11:14
 */
@Data
public class QueryParamMap extends HashMap<String, List<String>> {

    /**
     * 添加
     *
     * @param key   key
     * @param value value
     * @since 2023/1/17 11:31
     */
    public void add(String key, Object value) {
        if (Objects.isNull(value)) {
            return;
        }

        String valueStr = value.toString();

        List<String> list = get(key);
        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
            list.add(valueStr);
            put(key, list);

        } else {
            list.add(valueStr);
        }
    }

    /**
     * 添加
     *
     * @param key       key
     * @param valueList valueList
     * @since 2023/1/17 11:31
     */
    public void addAll(String key, List<?> valueList) {
        if (CollectionUtils.isEmpty(valueList)) {
            return;
        }

        List<String> list = get(key);
        if (CollectionUtils.isEmpty(list)) {
            put(key, convertList(valueList, null));

        } else {
            convertList(valueList, list);
        }
    }

    /**
     * 将list中的元素转换为字符串
     * <p>url参数中不会有对象
     *
     * @param src    源集合
     * @param target 目标集合
     * @return {@link List< String>}
     * @since 2023/1/17 18:04
     */
    private static List<String> convertList(List<?> src,
                                            @Nullable List<String> target) {
        if (Objects.isNull(target)) {
            target = new ArrayList<>(src.size());
        }

        for (Object i : src) {
            target.add(i.toString());
        }

        return target;
    }

    /**
     * 转换实体
     *
     * @param obj obj
     * @since 2023/1/17 17:45
     */
    public static QueryParamMap convertEntity(Object obj) {
        try {
            QueryParamMap map = new QueryParamMap();

            List<Field> fieldList = ReflectUtil.getFiledAsList(obj.getClass());

            for (Field field : fieldList) {
                String fieldName = field.getName();
                Method getter = ReflectUtil.getGetter(obj, fieldName);
                if (Objects.isNull(getter)) {
                    continue;
                }

                Object value = getter.invoke(obj);
                if (Objects.isNull(value)) {
                    continue;
                }

                // 是集合，使用addAll()
                if (value instanceof List) {
                    map.addAll(fieldName, (List<?>) value);
                    continue;
                }

                map.add(fieldName, value);
            }

            return map;

        } catch (Throwable e) {
            throw new QueryParamException(e);
        }
    }

    /**
     * 转换为url参数格式
     *
     * @return {@link String}
     * @since 2023/1/17 19:11
     */
    public String transferUrlParam() {
        return transferUrlParam(this);
    }

    /**
     * 转换为url参数格式
     *
     * @param queryParamMap url参数
     * @return {@link String}
     * @since 2023/1/17 19:11
     */
    public static String transferUrlParam(QueryParamMap queryParamMap) {
        StringBuilder urlBuilder = new StringBuilder();
        boolean isFirst = true;
        for (Map.Entry<String, List<String>> entry : queryParamMap.entrySet()) {
            String k = entry.getKey();
            List<String> list = entry.getValue();

            for (String v : list) {
                urlBuilder.append(isFirst ? "?" : "&")
                        .append(k)
                        .append("=")
                        .append(v);
            }

            isFirst = false;
        }

        return urlBuilder.toString();
    }
}
